package com.neurosky.ecg;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import com.neurosky.ecg.TGLibECG;
import com.neurosky.ecg.TGLibECGCallback;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class HelloAndroidECGSDK extends Activity {

	private static final String TAG = "HelloAndroidECGSDK";

	// New chart settings
	private LinearLayout lin;
	private String title = "Filtered ECG Signal";
	private XYSeries series;
	private XYMultipleSeriesDataset mDataset;
	private GraphicalView chart;
	private XYMultipleSeriesRenderer renderer;
	private Context context;
	private int addX = -1, addY;

	int[] xv = new int[3072];
	int[] yv = new int[3072];

	ToggleButton tb_demo;
	TextView tv_sdkVersion;
	TextView tv_heartRate, tv_rrInterval, tv_robust;
	TextView tv_rpeakDetected, tv_heartBeatCount, tv_hrv;
	TextView tv_mood, tv_heartAge, tv_stress;
	TextView tv_ssq, tv_lsq;

	private TGLibECG libECG;
	private int outputInterval = 30;
	private int heartAgeRecordNumber = 5;
	private int threshold = 3;
	private String user_name = "Mary";
	private int weight = 65;
	private int height = 170;
	private int age = 30;
	private boolean female = true;
	private String path = "";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.first_view);

		// set up toggle button
		tb_demo = (ToggleButton) findViewById(R.id.togglebuttonDemo);
		tb_demo.setEnabled(true);

		// SDK version
		tv_sdkVersion = (TextView) findViewById(R.id.textView2);
		tv_sdkVersion.setText("");

		// Heart Rate , R-R interval and RobustHeartRate display
		tv_heartRate = (TextView) findViewById(R.id.textView6);
		tv_heartRate.setText("");
		tv_rrInterval = (TextView) findViewById(R.id.textView8);
		tv_rrInterval.setText("");
		tv_robust = (TextView) findViewById(R.id.textView10);
		tv_robust.setText("");

		// RpeakDetected, HeaertBeatCount and HRV display
		tv_rpeakDetected = (TextView) findViewById(R.id.textView12);
		tv_rpeakDetected.setText("");
		tv_heartBeatCount = (TextView) findViewById(R.id.textView14);
		tv_heartBeatCount.setText("");
		tv_hrv = (TextView) findViewById(R.id.textView16);
		tv_hrv.setText("");

		// Mood, heartAge and Stress display
		tv_mood = (TextView) findViewById(R.id.textView18);
		tv_mood.setText("");
		tv_heartAge = (TextView) findViewById(R.id.textView20);
		tv_heartAge.setText("");
		tv_stress = (TextView) findViewById(R.id.textView22);
		tv_stress.setText("");

		// signal quality display
		tv_ssq = (TextView) findViewById(R.id.textView24);
		tv_ssq.setText("");
		tv_lsq = (TextView) findViewById(R.id.textView26);
		tv_lsq.setText("");

		libECG = new TGLibECG(ecgCallback);
		// turn off LogCat messages
		libECG.enableLogCatMessages(false);

		lin = (LinearLayout) findViewById(R.id.linear1);
		setECGChart();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
	}
	
	private void resetECG() {
		libECG.resetECGAnalysis();
		libECG.setSignalQualityThreshold(threshold);
		libECG.setHRVOutputInterval(outputInterval);
		libECG.setMoodOutputPoint(outputInterval);
		libECG.setHeartAgeOutputPoint(outputInterval);
		libECG.setHeartAgeParameters(user_name, age, path);
		libECG.setHeartAgeRecordNumber(heartAgeRecordNumber);
		libECG.setStressOutputInterval(outputInterval);
		libECG.setStressParameters(user_name, female, age, height, weight, path);
		
		tv_sdkVersion.setText(libECG.getVersion());
		tv_heartRate.setText("");
		tv_rrInterval.setText("");
		tv_robust.setText("");
		tv_rpeakDetected.setText("");
		tv_heartBeatCount.setText("");
		tv_hrv.setText("");
		tv_mood.setText("");
		tv_heartAge.setText("");
		tv_stress.setText("");
		tv_ssq.setText("");
		tv_lsq.setText("");

		chart.invalidate();
	}
	

	public void onDemoClicked(View view) {
		boolean on = ((ToggleButton) view).isChecked();
		if (on) {
			tb_demo.setEnabled(false);
			resetECG();
			Runnable d = new startParse();
			new Thread(d).start();
		} else {
			Toast.makeText(context, "Processing!", Toast.LENGTH_LONG).show();
			tb_demo.setEnabled(false);
		}
	}

	/* set ECG Chart plotting features */
	public void setECGChart() {
		context = getApplicationContext();
		series = new XYSeries(title);

		mDataset = new XYMultipleSeriesDataset();

		mDataset.addSeries(series);

		int color = Color.RED;
		PointStyle style = PointStyle.POINT;
		renderer = buildRenderer(color, style, true);

		setChartSettings(renderer, "Time", "Amplitude", 0, 3072, -5000, 10000,
				Color.WHITE, Color.GREEN);
		chart = ChartFactory.getLineChartView(context, mDataset, renderer);

		lin.addView(chart, new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT));

	}

	/**
	 * XYMultipleSeriesRenderer
	 */
	protected XYMultipleSeriesRenderer buildRenderer(int color,
			PointStyle style, boolean fill) {
		XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();

		// set up renderer
		XYSeriesRenderer r = new XYSeriesRenderer();
		r.setColor(color);
		r.setPointStyle(style);
		r.setFillPoints(fill);
		r.setLineWidth(2);
		renderer.addSeriesRenderer(r);

		return renderer;
	}

	/**
	 * setChartSettings
	 */
	protected void setChartSettings(XYMultipleSeriesRenderer renderer,
			String xTitle, String yTitle, double xMin, double xMax,
			double yMin, double yMax, int axesColor, int labelsColor) {
		// set up chart
		renderer.setPointSize(3);
		renderer.setZoomButtonsVisible(true);
		renderer.setShowGrid(true);
		renderer.setXAxisMin(xMin);
		renderer.setXAxisMax(xMax);
		renderer.setYAxisMin(yMin);
		renderer.setYAxisMax(yMax);
		renderer.setXLabels(10);
		renderer.setYLabels(10);
		renderer.setMarginsColor(Color.BLACK);
		renderer.setLabelsColor(labelsColor);

		renderer.setBackgroundColor(axesColor);
		renderer.setApplyBackgroundColor(true);

		renderer.setShowLabels(true);

		renderer.setXTitle(xTitle);
		renderer.setYTitle(yTitle);

		renderer.setPanEnabled(true);
		renderer.setZoomEnabled(true, false);
	}

	/**
	 * updateChart
	 */
	private void updateChart(int rawdata) {
		addY = rawdata;

		mDataset.removeSeries(series);

		int length = series.getItemCount();
		if (length > 3071) {
			series.clear();
			addX = 0;
		}
		series.add(addX++, addY);
		mDataset.addSeries(series);

		chart.invalidate();

	}

	private class startParse implements Runnable {

		public startParse() {
		}

		@Override
		public void run() {
			String line = "";
			try {
				InputStream is = getResources().openRawResource(
						R.raw.raw_sample);
				BufferedReader br = new BufferedReader(
						new InputStreamReader(is));

				int poorSignal = 200;
				int count = 0;
				while ((line = br.readLine()) != null) {
					short raw = Short.parseShort(line);
					libECG.requestECGAnalysis(raw, poorSignal);
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					count++;
					if (count % 512 == 0) {
						tv_ssq.post(new Runnable() {

							@Override
							public void run() {
								tv_ssq.setText(String.valueOf(libECG
										.getSignalQuality()));
							}
						});
					}
				}
				tv_lsq.post(new Runnable() {

					@Override
					public void run() {
						tv_lsq.setText(String.valueOf(libECG
								.getOverallSignalQuality()));
					}
				});
				tb_demo.post(new Runnable() {

					@Override
					public void run() {
						tb_demo.setEnabled(true);
						tb_demo.setChecked(false);
					}
				});
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public TGLibECGCallback ecgCallback = new TGLibECGCallback() {
		@Override
		public void dataReceived(int key, Object data) {
			runOnUiThread(new ecgData(key, data));
		}
	};

	public class ecgData implements Runnable {
		int key;
		Object data;

		public ecgData(int k, Object d) {
			key = k;
			data = d;
		}

		@Override
		public void run() {
			switch (key) {
			case TGLibECG.MSG_ECG_SMOOTHED_WAVE:
				updateChart((Integer) data);
				break;
			case TGLibECG.MSG_ECG_HEART_RATE:
				tv_heartRate.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_R2R_INTERVAL:
				tv_rrInterval.setText(String.valueOf(data));
				tv_heartBeatCount.setText(String.valueOf(libECG
						.getTotalRRintNum()));
				break;
			case TGLibECG.MSG_ECG_HRV:
				tv_hrv.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_RPEAK_DETECTED:
				if((Integer)data == 1) {
					tv_rpeakDetected.setText(String.valueOf(data));
				}
				break;
			case TGLibECG.MSG_ECG_MOOD:
				tv_mood.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_STRESS:
				tv_stress.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_HEART_AGE:
				tv_heartAge.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_HEART_RATE_ROBUST:
				tv_robust.setText(String.valueOf(data));
				break;
			case TGLibECG.MSG_ECG_EXCEPTION:
				Toast.makeText(context, String.valueOf(data), Toast.LENGTH_LONG)
						.show();
				break;
			}
		}
	}

}
